package com.powernode.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.constant.MenuConstant;
import com.powernode.domain.SysRole;
import com.powernode.domain.SysRoleMenu;
import com.powernode.mapper.SysRoleMapper;
import com.powernode.mapper.SysRoleMenuMapper;
import com.powernode.service.SysRoleMenuService;
import com.powernode.service.SysRoleService;
import com.powernode.utils.AuthUtil;
import com.powernode.vo.RoleAndMenu;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@CacheConfig(cacheNames = "com.powernode.service.impl.SysRoleServiceImpl") // 存在于redis中的名字
@Slf4j
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService{
    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    /**
     * 查询角色表，首先回去缓存中查询，如果缓存中查询不到就会执行下面的语句去数据库中进行查询
     * @return
     */
    @Override
    @Cacheable(key = MenuConstant.ROLE_LIST)
    public List<SysRole> list() {
        return sysRoleMapper.selectList(new LambdaQueryWrapper<SysRole>()
        .orderByDesc(SysRole::getCreateTime)
        );
    }

    /**
     * 保存角色和角色菜单表，此时更新了角色表因此需要删除缓存，又因为操作了两张表需要添加事务
     * @param roleAndMenu
     */
    @Override
    @Transactional
    @CacheEvict(key = MenuConstant.ROLE_LIST)
    public void saveRoleAndMenu(RoleAndMenu roleAndMenu) {
        // 1. 补全角色信息
        SysRole sysRole = new SysRole();
        sysRole.setRoleName(roleAndMenu.getRoleName());
        sysRole.setRemark(roleAndMenu.getRemark());
        sysRole.setCreateTime(new Date());
        sysRole.setCreateUserId(Long.valueOf(AuthUtil.getLoginUserId()));

        // 2. 添加进角色表
        sysRoleMapper.insert(sysRole);

        // 3. 添加到角色菜单表(选择批量添加)
        List<Long> menuIdList = roleAndMenu.getMenuIdList();

        List<SysRoleMenu> sysRoleMenuList = menuIdList.stream().map(item -> {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(sysRole.getRoleId());
            sysRoleMenu.setMenuId(item);
            return sysRoleMenu;
        }).collect(Collectors.toList());

        boolean b = sysRoleMenuService.saveBatch(sysRoleMenuList);

        if (!b) {
            log.error("角色和权限菜单添加失败！");
        }
    }

    @Override
    public RoleAndMenu selectRoleAndMenuById(Long rid) {
        RoleAndMenu roleAndMenu = new RoleAndMenu();

        // 1. 根据rid查询role
        SysRole sysRole = sysRoleMapper.selectById(rid);
        if (sysRole == null) {
            log.error("传入的角色id有问题！");
            return null;
        }
        roleAndMenu.setRoleName(sysRole.getRoleName());
        roleAndMenu.setRemark(sysRole.getRemark());

        // 2. 根据rid查询menuIdList
        List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, rid));
        List<Long> menuIdList = sysRoleMenuList.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());

        roleAndMenu.setMenuIdList(menuIdList);

        return roleAndMenu;
    }

    /**
     * 删除role并删除相应的菜单权限和缓存
     * @param roleIdList
     */
    @Override
    @CacheEvict(key = MenuConstant.ROLE_LIST)
    @Transactional
    public void deleteRoleAndMenu(List<Long> roleIdList) {
        // 1. 循环列表删除相应的role
        roleIdList.forEach(item -> {
            // 2. 删除相应的role
            sysRoleMapper.deleteById(item);

            // 3. 删除对应的角色权限列表
            sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, item));
        });

    }

    /**
     * 修改role和权限信息
     * @param roleAndMenu
     */
    @Override
    @Transactional
    public void modifyRoleAndMenu(RoleAndMenu roleAndMenu) {
        // 1. 修改role
        SysRole newSysRole = SysRole.builder().roleId(roleAndMenu.getRoleId())
                .roleName(roleAndMenu.getRoleName())
                .remark(roleAndMenu.getRemark())
                .createTime(new Date())
                .createUserId(Long.valueOf(AuthUtil.getLoginUserId()))
                .build();
        sysRoleMapper.updateById(newSysRole);


        // 2. 修改角色权限表
        sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleAndMenu.getRoleId()));

        // 3. 添加新的权限
        List<SysRoleMenu> sysRoleMenuList = roleAndMenu.getMenuIdList().stream().map(item -> {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(item);
            sysRoleMenu.setRoleId(roleAndMenu.getRoleId());
            return sysRoleMenu;
        }).collect(Collectors.toList());

        sysRoleMenuService.saveBatch(sysRoleMenuList);

    }
}
